home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / mach / sun4c.md / addsub.c < prev    next >
C/C++ Source or Header  |  1989-08-17  |  5KB  |  197 lines

  1. #ifdef sccsid
  2. static char     sccsid[] = "@(#)addsub.c 1.5 88/02/08 SMI";
  3. #endif
  4.  
  5. /*
  6.  * Copyright (c) 1988 by Sun Microsystems, Inc.
  7.  */
  8.  
  9. /*
  10.  * This whole file refuses to lint.
  11.  */
  12. #ifndef lint
  13. #include <sun4/fpu/fpu_simulator.h>
  14. #include <sun4/fpu/globals.h>
  15.  
  16. PRIVATE void
  17. true_add(px, py, pz)
  18.     unpacked       *px, *py, *pz;
  19.  
  20. {
  21.     unpacked       *pt;
  22.  
  23.     if ((int) px->fpclass < (int) py->fpclass) {    /* Reverse. */
  24.         pt = py;
  25.         py = px;
  26.         px = pt;
  27.     }
  28.     /* Now class(x) >= class(y). */
  29.     switch (px->fpclass) {
  30.     case fp_quiet:        /* NaN + x -> NaN */
  31.     case fp_signaling:    /* NaN + x -> NaN */
  32.     case fp_infinity:    /* Inf + x -> Inf */
  33.     case fp_zero:        /* 0 + 0 -> 0 */
  34.         *pz = *px;
  35.         return;
  36.     default:
  37.         if (py->fpclass == fp_zero) {
  38.             *pz = *px;
  39.             return;
  40.         }
  41.     }
  42.     /* Now z is normal or subnormal. */
  43.     /* Now y is normal or subnormal. */
  44.     if (px->exponent < py->exponent) {    /* Reverse. */
  45.         pt = py;
  46.         py = px;
  47.         px = pt;
  48.     }
  49.     /* Now class(x) >= class(y). */
  50.     pz->fpclass = px->fpclass;
  51.     pz->sign = px->sign;
  52.     pz->exponent = px->exponent;
  53.  
  54.     if (px->exponent == py->exponent) {    /* no pre-alignment required */
  55.         pz->significand[2] = 0;
  56.         pz->significand[1] = px->significand[1] + py->significand[1];
  57.         if ((pz->significand[1] < px->significand[1]) &&
  58.             (pz->significand[1] < py->significand[1]))
  59.             py->significand[0]++;
  60.         pz->significand[0] = px->significand[0] + py->significand[0];
  61.     } else {        /* pre-alignment required */
  62.         fpu_rightshift(py, pz->exponent - py->exponent);
  63.         pz->significand[2] = py->significand[2];
  64.         pz->significand[1] = px->significand[1] + py->significand[1];
  65.         if ((pz->significand[1] < px->significand[1]) &&
  66.             (pz->significand[1] < py->significand[1]))
  67.             py->significand[0]++;    /* Carry out occurred. */
  68.         pz->significand[0] = px->significand[0] + py->significand[0];
  69.         if ((pz->significand[0] >= px->significand[0]) ||
  70.             (pz->significand[0] >= py->significand[0])) {    /* No carry out
  71.                                      * occurred. */
  72.             return;
  73.         }
  74.     }
  75.     /* Handle carry out of msb. */
  76.     fpu_rightshift(pz, 1);
  77.     pz->significand[0] |= 0x80000000;    /* Carried out bit. */
  78.     pz->exponent++;        /* Renormalize. */
  79.     return;
  80. }
  81.  
  82. PRIVATE void
  83. true_sub(px, py, pz)
  84.     unpacked       *px, *py, *pz;
  85.  
  86. {
  87.     unpacked       *pt;
  88.  
  89.     if ((int) px->fpclass < (int) py->fpclass) {    /* Reverse. */
  90.         pt = py;
  91.         py = px;
  92.         px = pt;
  93.     }
  94.     /* Now class(x) >= class(y). */
  95.     *pz = *px;        /* Tentative difference: x. */
  96.     switch (pz->fpclass) {
  97.     case fp_quiet:        /* NaN - x -> NaN */
  98.     case fp_signaling:    /* NaN - x -> NaN */
  99.         return;
  100.     case fp_infinity:    /* Inf - x -> Inf */
  101.         if (py->fpclass == fp_infinity) {
  102.             fpu_error_nan(pz);    /* Inf - Inf -> NaN */
  103.             pz->fpclass = fp_quiet;
  104.         }
  105.         return;
  106.     case fp_zero:        /* 0 + 0 -> 0 */
  107.         pz->sign = (fp_direction == fp_negative);
  108.         return;
  109.     default:
  110.         if (py->fpclass == fp_zero)
  111.             return;
  112.     }
  113.  
  114.     /* x and y are both normal or subnormal. */
  115.  
  116.     if (px->exponent < py->exponent) {    /* Reverse. */
  117.         pt = py;
  118.         py = px;
  119.         px = pt;
  120.     }
  121.     /* Now exp(x) >= exp(y). */
  122.     pz->fpclass = px->fpclass;
  123.     pz->sign = px->sign;
  124.     pz->exponent = px->exponent;
  125.  
  126.     if (px->exponent == py->exponent) {    /* no pre-alignment required */
  127.  
  128.         pz->significand[2] = 0;
  129.         if (px->significand[1] >= py->significand[1]) {
  130.             pz->significand[1] = px->significand[1] - py->significand[1];
  131.         } else {
  132.             pz->significand[1] = (0xffffffff - py->significand[1]) + (1 + px->significand[1]);
  133.             px->significand[0]--;
  134.         }
  135.         if (px->significand[0] >= py->significand[0]) {
  136.             pz->significand[0] = px->significand[0] - py->significand[0];
  137.             if ((pz->significand[0] | pz->significand[1]) == 0) {    /* exact zero result */
  138.                 pz->sign = (fp_direction == fp_negative);
  139.                 pz->fpclass = fp_zero;
  140.                 return;
  141.             }
  142.         } else {    /* sign reversal occurred */
  143.             pz->sign = py->sign;
  144.             if (pz->significand[1] != 0) {    /* complement lower
  145.                              * significand. */
  146.                 pz->significand[1] = 0x00000000 - pz->significand[1];
  147.                 pz->significand[0] = py->significand[0] - px->significand[0] - 1;
  148.             } else
  149.                 pz->significand[0] = py->significand[0] - px->significand[0];
  150.         }
  151.     } else {        /* pre-alignment required */
  152.         fpu_rightshift(py, pz->exponent - py->exponent);
  153.         if (py->significand[2] == 0)
  154.             pz->significand[2] = 0;
  155.         else {        /* Propagate carry from non-zero bits shifted
  156.                  * out. */
  157.             pz->significand[2] = 1 + (0xffffffff - py->significand[2]);
  158.             px->significand[1]--;
  159.             if (px->significand[1] == 0xffffffff)
  160.                 px->significand[0]--;
  161.         }
  162.         if (px->significand[1] >= py->significand[1]) {
  163.             pz->significand[1] = px->significand[1] - py->significand[1];
  164.         } else {
  165.             pz->significand[1] = (0xffffffff - py->significand[1]) + (1 + px->significand[1]);
  166.             px->significand[0]--;
  167.         }
  168.         pz->significand[0] = px->significand[0] - py->significand[0];
  169.     }
  170.     fpu_normalize(pz);
  171.     return;
  172. }
  173.  
  174. void
  175. _fp_add(px, py, pz)
  176.     unpacked       *px, *py, *pz;
  177.  
  178. {
  179.     if (px->sign == py->sign)
  180.         true_add(px, py, pz);
  181.     else
  182.         true_sub(px, py, pz);
  183. }
  184.  
  185. void
  186. _fp_sub(px, py, pz)
  187.     unpacked       *px, *py, *pz;
  188.  
  189. {
  190.     py->sign = 1 - py->sign;
  191.     if (px->sign == py->sign)
  192.         true_add(px, py, pz);
  193.     else
  194.         true_sub(px, py, pz);
  195. }
  196. #endif /* lint */
  197.